home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Online / hsc / source / ugly / infile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-02  |  24.1 KB  |  1,172 lines

  1. /*
  2.  * This source code is part of hsc, a html-preprocessor,
  3.  * Copyright (C) 1993-1997  Thomas Aglassinger
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20. /*
  21.  * ugly/infile.c
  22.  *
  23.  * ugly input file functions
  24.  *
  25.  * updated: 29-Sep-1997
  26.  * created:  8-Jul-1995
  27.  */
  28.  
  29. /*
  30.  * TODO:
  31.  *
  32.  * - handle errors within expstr (no mem)
  33.  * - more elegant handling of inunget( '\n' );
  34.  */
  35.  
  36. /*
  37.  * includes
  38.  */
  39. #include <ctype.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43.  
  44. #include "utypes.h"
  45. #include "expstr.h"
  46. #include "ustring.h"
  47. #include "fname.h"              /* for CRLF_SHIT */
  48.  
  49. #define NOEXTERN_UGLY_FILE_H
  50. #include "infile.h"
  51. #include "umemory.h"
  52.  
  53. /* buffer size for fgets() in ugly_infgetc() */
  54. #define INF_FGETS_BUFSIZE 1024
  55.  
  56. /*
  57.  * global vars
  58.  */
  59. STRPTR FNAME_STDIN = "STDIN";   /* filename for stdin (CONSTANT) */
  60.  
  61. /*
  62.  * debugging defines
  63.  */
  64. #define DINF "*infile* "
  65.  
  66. #ifdef D
  67. #undef D
  68. #endif
  69.  
  70. #if DEBUG_UGLY_INFILE | 0
  71. #define D( x ) x
  72. #else
  73. #define D( x )                  /* nufin */
  74. #endif
  75.  
  76. /*
  77.  * local vars
  78.  */
  79.  
  80. /* forward references */
  81. BOOL infget_skws(INFILE * inpf);
  82. static VOID del_infilepos_nddata(APTR data);
  83.  
  84. /*
  85.  *
  86.  * local functions (not exported into header)
  87.  *
  88.  */
  89.  
  90. /*
  91.  * default_whtspc, default_normch
  92.  *
  93.  * default methods for infgetw() to determine if
  94.  * a char is a whitespace or normal char.
  95.  */
  96. static BOOL default_whtspc(int ch)
  97. {
  98.     if (strchr(" \t", ch) != NULL)
  99.     {
  100.         return TRUE;
  101.     }
  102.     else
  103.     {
  104.         return FALSE;
  105.     }
  106. }
  107.  
  108. static BOOL default_normch(int ch)
  109. {
  110.     if (isalnum(ch) || (ch == '_'))
  111.     {
  112.         return TRUE;
  113.     }
  114.     else
  115.     {
  116.         return FALSE;
  117.     }
  118. }
  119.  
  120. /*
  121.  * update_wpos
  122.  *
  123.  * update word position with the values of the
  124.  * "normal" position in input file
  125.  *
  126.  */
  127. static VOID update_wpos(INFILE * inpf)
  128. {
  129.     inpf->wpos_x = inpf->pos_x;
  130.     inpf->wpos_y = inpf->pos_y;
  131. }
  132.  
  133. /*
  134.  *-------------------------------------
  135.  * constructor/destructor
  136.  *-------------------------------------
  137.  */
  138.  
  139. /*
  140.  * reset_inpf
  141.  *
  142.  * reset a INFILE struct (set all items to NULL)
  143.  * (only called by con/destructor)
  144.  */
  145. static VOID reset_infile(INFILE * inpf)
  146. {
  147.     inpf->infile = NULL;
  148.     inpf->filename = NULL;
  149.     inpf->lnbuf = NULL;
  150.     inpf->wordbuf = NULL;
  151.     inpf->wspcbuf = NULL;
  152.  
  153.     inpf->filepos = 0;
  154.     inpf->pos_x = 0;
  155.     inpf->pos_y = 0;
  156.     update_wpos(inpf);
  157.  
  158.     inpf->base_x = 0;
  159.     inpf->base_y = 0;
  160.     inpf->pos_list = NULL;
  161.     inpf->pos_count = 0;
  162.     inpf->eof_reached = FALSE;
  163.     inpf->out_of_mem = FALSE;
  164.     inpf->skipped_ws = FALSE;
  165.     inpf->closed = FALSE;
  166.     inpf->is_nc = NULL;
  167.     inpf->is_ws = NULL;
  168. }
  169.  
  170. /*
  171.  * remove INFILE structure
  172.  */
  173. static VOID del_infile(INFILE * inpf)
  174. {
  175.     if (inpf)
  176.     {
  177.         D(
  178.              {
  179.              fprintf(stderr, DINF "close file");
  180.              if (inpf->filename)
  181.              fprintf(stderr, " \"%s\"", inpf->filename);
  182.              fprintf(stderr, "\n");
  183.              }
  184.         );
  185.  
  186.         if (inpf->pos_count)
  187.         {
  188.             inpf->closed = TRUE;
  189.             D(fprintf(stderr, DINF "  (%lu fpos-req left)\n",
  190.                       inpf->pos_count));
  191.         }
  192.         else
  193.         {
  194.             /* close file */
  195.             if (inpf->infile)
  196.                 fclose(inpf->infile);
  197.  
  198.             /* remove pos-requests */
  199.             del_dllist(inpf->pos_list);
  200.  
  201.             /* release mem */
  202.             ufreestr(inpf->filename);
  203.             del_estr(inpf->lnbuf);
  204.             del_estr(inpf->wordbuf);
  205.             del_estr(inpf->wspcbuf);
  206.  
  207.             /* reset all items */
  208.             reset_infile(inpf);
  209.  
  210.             /* release whole structure */
  211.             ufree(inpf);
  212.         }
  213.     }
  214. }
  215.  
  216. /*
  217.  * init INFILE structure
  218.  */
  219. static INFILE *init_infile(CONSTRPTR name, size_t buf_step, size_t word_step)
  220. {
  221.     INFILE *inpf = (INFILE *) umalloc(sizeof(INFILE));
  222.  
  223.     if (inpf)
  224.     {
  225.         /* check for buffer-stepsize */
  226.         if (!buf_step)
  227.             buf_step = IF_BUFFER_VALUE;
  228.         if (!word_step)
  229.             word_step = IF_BUFFER_VALUE;
  230.  
  231.         /* reset all items */
  232.         reset_infile(inpf);
  233.  
  234.         /* clone filename (NULL=stdin) */
  235.         if (name)
  236.             inpf->filename = strclone(name);
  237.  
  238.         /* init wordbuffers */
  239.         inpf->lnbuf = init_estr(buf_step);
  240.         inpf->wordbuf = init_estr(word_step);
  241.         inpf->wspcbuf = init_estr(word_step);
  242.         inpf->pos_list = init_dllist(del_infilepos_nddata);
  243.         inpf->pos_count = 0;
  244.  
  245.         /* check if init ok */
  246.         if (!((inpf->filename || !(name))
  247.               && inpf->lnbuf
  248.               && inpf->wordbuf
  249.               && inpf->wspcbuf))
  250.         {
  251.             /* remove infile, */
  252.             /* set return value to NULL */
  253.             del_infile(inpf);
  254.             inpf = NULL;
  255.         }
  256.     }
  257.  
  258.     return (inpf);
  259. }
  260.  
  261. /*
  262.  *=====================================
  263.  *
  264.  * exported functions
  265.  *
  266.  *=====================================
  267.  */
  268.  
  269. /*
  270.  *-------------------------------------
  271.  * functions to get info about infile
  272.  *-------------------------------------
  273.  */
  274.  
  275. /*
  276.  * infget_x
  277.  *
  278.  * get colum of current line
  279.  */
  280. ULONG infget_x(INFILE * inpf)
  281. {
  282.     return (inpf->pos_x + inpf->base_x);
  283. }
  284.  
  285. /*
  286.  * infget_y
  287.  *
  288.  * get current line
  289.  */
  290. ULONG infget_y(INFILE * inpf)
  291. {
  292.     return (inpf->pos_y + inpf->base_y);
  293. }
  294.  
  295. /*
  296.  * infget_wx
  297.  *
  298.  * get colum of current word
  299.  */
  300. ULONG infget_wx(INFILE * inpf)
  301. {
  302.     return (inpf->wpos_x + inpf->base_x);
  303. }
  304.  
  305. /*
  306.  * infget_y
  307.  *
  308.  * get line of current word
  309.  */
  310. ULONG infget_wy(INFILE * inpf)
  311. {
  312.     return (inpf->wpos_y + inpf->base_y);
  313. }
  314.  
  315. /*
  316.  * infget_skws
  317.  *
  318.  * get status of skipped_ws
  319.  */
  320. BOOL infget_skws(INFILE * inpf)
  321. {
  322.     return (inpf->skipped_ws);
  323. }
  324.  
  325. /*
  326.  * infget_fname
  327.  *
  328.  * get name of file
  329.  */
  330. STRPTR infget_fname(INFILE * inpf)
  331. {
  332.     if (inpf->filename)
  333.         return (inpf->filename);
  334.     else
  335.         return (FNAME_STDIN);
  336. }
  337.  
  338. /*
  339.  * infeof
  340.  *
  341.  * check if end of input file reached
  342.  *
  343.  * params: inpf...input file to check
  344.  * result: if end of input file reached, 0 is returned,
  345.  *         else a value < 0 (compare feof() of some
  346.  *         compilers)
  347.  */
  348. int infeof(INFILE * inpf)
  349. {
  350.     if (inpf->eof_reached == TRUE)
  351.         return EOF;
  352.     else
  353.         return 0;
  354. }
  355.  
  356. /*
  357.  * infget_cws (get current whites spaces)
  358.  *
  359.  * get string that contains all white-spaces
  360.  * skipped within the last call of infgetw()
  361.  */
  362. STRPTR infgetcws(INFILE * inpf)
  363. {
  364.     return (estr2str(inpf->wspcbuf));
  365. }
  366.  
  367. /*
  368.  * infget_cw (get current word)
  369.  *
  370.  * get string that contains all chars
  371.  * read within the last call of infgetw()
  372.  */
  373. STRPTR infgetcw(INFILE * inpf)
  374. {
  375.     return (estr2str(inpf->wordbuf));
  376. }
  377.  
  378. /*
  379.  *-------------------------------------
  380.  * functions to set methods
  381.  *-------------------------------------
  382.  */
  383.  
  384. /*
  385.  * set_inf_whtspc
  386.  *
  387.  * set function to check if a char is a whitespace.
  388.  * this func is called by infgetw() to determine if
  389.  * the begining of a word is reached.
  390.  */
  391. void set_whtspc(INFILE * inpf, BOOL(*iswsfn) (int ch))
  392. {
  393.     if (inpf)
  394.     {
  395.         inpf->is_ws = iswsfn;
  396.     }
  397. }
  398.  
  399. /*
  400.  * set_inf_normch
  401.  *
  402.  * set function to check if a char is a "normal" char.
  403.  * this function is called by infgetw() to determine if
  404.  * the end of a word is reached
  405.  */
  406. void set_normch(INFILE * inpf, BOOL(*isncfn) (int ch))
  407. {
  408.     if (inpf)
  409.     {
  410.         inpf->is_nc = isncfn;
  411.     }
  412. }
  413.  
  414. /*
  415.  *-------------------------------------
  416.  * functions for open & close
  417.  *-------------------------------------
  418.  */
  419.  
  420. /*
  421.  * infclose1
  422.  *
  423.  * close INFILE entry, free all mem allocated by it
  424.  *
  425.  * result: always 0
  426.  *
  427.  */
  428. int infclose1(INFILE * inpf)
  429. {
  430.     del_infile(inpf);
  431.  
  432.     return (0);
  433. }
  434.  
  435. /*
  436.  * infopen
  437.  *
  438.  * params: name.......name of input file to open
  439.  *         step_size..portion of memory buffers should be increased with
  440.  * result: ptr to INFILE entry or NULL if error;
  441.  *
  442.  * NOTE: if result = NULL, but errno=0, too, then there
  443.  *       wasn't enough mem for the line-buffer. in this
  444.  *       case, calling perror() will not produce a proper
  445.  *       error message.
  446.  *
  447.  * NOTE: don't forget to set errno=0 before calling infopen().
  448.  */
  449. INFILE *infopen(CONSTRPTR name, size_t step_size)
  450. {
  451. #define FILEMODE "rb"
  452. #define INF_DEFAULT_HUNKSIZE (32*1024)
  453.     INFILE *inpf = NULL;
  454.     FILE *file = NULL;
  455.     long int filesize = 0;
  456.     size_t buf_size = 4096;
  457.  
  458.     /* open input file or assign stdin to input file */
  459.     if (name)
  460.     {
  461.         file = fopen(name, FILEMODE);
  462.         if (file)
  463.         {
  464.             /* evaluate size of file and set
  465.              * buf_size accroding to it. */
  466.  
  467.             fseek(file, 0, SEEK_END);
  468.             filesize = ftell(file);
  469.             if (filesize == -1)
  470.                 buf_size = INF_DEFAULT_HUNKSIZE;
  471.             else
  472.                 buf_size = filesize + (filesize / 16) + 1;
  473.             rewind(file);
  474.             D(fprintf(stderr, "*infile* file=%ld -> bufsz=%lu, wdsz=%lu \n",
  475.                       filesize, buf_size, step_size));
  476.         }
  477.     }
  478.     else
  479.     {
  480.         file = stdin;
  481.         buf_size = INF_DEFAULT_HUNKSIZE;
  482.     }
  483.  
  484.     /* init infile */
  485.     if (file)
  486.     {
  487.         inpf = init_infile(name, buf_size, step_size);
  488.         if (inpf)
  489.             inpf->infile = file;
  490.     }
  491.  
  492.     /* read whole file into file lnbuf */
  493.     if (inpf)
  494.     {
  495.         if (file != stdin)
  496.         {
  497.             /* read whole file into buffer directly */
  498.             /* (perverted and experimental, but faaast) */
  499.             D(fprintf(stderr, "*infile*  filesize=%ld\n", filesize));
  500.             filesize = fread(inpf->lnbuf->es_data, 1, (size_t) filesize, file);
  501.             inpf->lnbuf->es_len = (size_t) filesize;
  502.             inpf->lnbuf->es_data[filesize] = 0;
  503.         }
  504.         else
  505.         {
  506.             /* read stdin, line by line */
  507.             STRPTR buf = (STRPTR) umalloc(INF_FGETS_BUFSIZE);   /* alloc buffer */
  508.             STRPTR restr = buf; /* result of fgets() (dummy init) */
  509.             BOOL ok = (buf != NULL);
  510.  
  511.             D(fprintf(stderr, "*infile*  filesize=STDIN\n"));
  512.             while (!feof(inpf->infile) && ok)
  513.             {
  514.                 restr = fgets(buf, INF_FGETS_BUFSIZE, inpf->infile);
  515.                 if (restr)
  516.                 {
  517.                     ok = app_estr(inpf->lnbuf, restr);
  518.                     D(
  519.                          {
  520.                          restr[20] = 0;
  521.                          fprintf(stderr, "*infile*  line=`%s'\n", restr);
  522.                          }
  523.                     );
  524.                 }
  525.             }
  526.  
  527.             ufree(buf);         /* free buffer */
  528.         }
  529.         D(fprintf(stderr, "*infile*  file read\n"));
  530.     }
  531.  
  532.     return (inpf);              /* return input file */
  533. }
  534.  
  535. /*
  536.  * infopen_str
  537.  *
  538.  * open a string as an input file
  539.  *
  540.  * params: fname......pseudo filename the string should have
  541.  *         s..........string that should be handled as a file
  542.  *         step_size..portion of memory buffers should be increased with
  543.  * result: ptr to INFILE entry or NULL if error;
  544.  *
  545.  * NOTE: a copy of the passed string is created. so you can
  546.  *       modify or release the string after calling inopen_str()
  547.  */
  548. INFILE *infopen_str(CONSTRPTR name, CONSTRPTR s, size_t step_size)
  549. {
  550.     /* init file */
  551.     INFILE *inpf = init_infile(name, strlen(s) + 1, step_size);
  552.  
  553.     if (inpf)
  554.     {
  555.         /* copy string to line buffer */
  556.         BOOL ok = set_estr(inpf->lnbuf, s);
  557.  
  558.         if (!ok)
  559.         {
  560.             del_infile(inpf);
  561.             inpf = NULL;
  562.         }
  563.     }
  564.  
  565.     return (inpf);              /* return input file */
  566. }
  567.  
  568. /*
  569.  *-------------------------------------
  570.  * functions to get text from infile
  571.  *-------------------------------------
  572.  */
  573.  
  574. /*
  575.  * ugly_infgetc
  576.  *
  577.  *
  578.  */
  579. int ugly_infgetc(INFILE * inpf)
  580. {
  581.     int result = EOF;
  582.  
  583. #if 0
  584.     fprintf(stderr, "** ingetch( \"%s\" at %p\n", inpf->filename, inpf);
  585. #endif
  586.     if (inpf && (!inpf->eof_reached))
  587.     {
  588.         STRPTR lnbuf_str = estr2str(inpf->lnbuf);
  589.  
  590.         /*
  591.          * if at end of line buffer, scan next line
  592.          * before proceding
  593.          */
  594.         if (lnbuf_str[inpf->filepos] == 0)
  595.         {
  596.             inpf->eof_reached = TRUE;
  597.         }
  598.  
  599.         /*
  600.          * check wether to return EOF or char from
  601.          * line buffer
  602.          */
  603.         if (inpf->eof_reached == FALSE)
  604.         {
  605.             /* set last char as result */
  606.             lnbuf_str = estr2str(inpf->lnbuf);
  607.             result = (UBYTE) lnbuf_str[inpf->filepos];
  608.             if (result)
  609.             {                   /* goto next char in buf */
  610.                 inpf->pos_x++;
  611.                 inpf->filepos++;
  612.             }
  613.         }
  614.  
  615.         /* update line number */
  616.         if (result == '\n')
  617.         {
  618.             inpf->pos_y++;
  619.             inpf->pos_x = 0;
  620.         }
  621.     }
  622.  
  623.     return (result);
  624. }
  625.  
  626. /*
  627.  * infgetc
  628.  *
  629.  * read next char from file, update word-position
  630.  */
  631. int infgetc(INFILE * inpf)
  632. {
  633.     /* read char */
  634.     int ch = ugly_infgetc(inpf);
  635.  
  636.     /* update word position */
  637.     update_wpos(inpf);
  638.  
  639. #if 0                           /* TODO: remove this */
  640.     /* TODO: this is shit */
  641.     if (ch == '\n')
  642.     {
  643.         inpf->wpos_y--;
  644.     }
  645. #endif
  646.  
  647.     return (ch);
  648. }
  649.  
  650. /*
  651.  *-------------------------------------
  652.  * functions to unget text from infile
  653.  *-------------------------------------
  654.  */
  655.  
  656. /*
  657.  * ugly_inungetc
  658.  *
  659.  * write char back to stream; comparable to ansi's ungetc()
  660.  *
  661.  * params: inpf...input file
  662.  *         ch.....char to write back
  663.  * result: ch, if sucessful, else EOF
  664.  */
  665. static int ugly_inungetc(int ch, INFILE * inpf)
  666. {
  667.     int result = EOF;
  668.  
  669.     if (inpf && (inpf->filepos))
  670.     {
  671.         STRPTR lnbuf_str = estr2str(inpf->lnbuf);
  672.  
  673.         /* update file position */
  674.         inpf->filepos--;
  675.  
  676.         /* write back char */
  677.         lnbuf_str[inpf->filepos] = ch;
  678.         result = ch;
  679.  
  680.         /* handle LF */
  681.         if (ch == '\n')
  682.         {
  683.             result = ch;
  684.             inpf->pos_y--;
  685.             inpf->pos_x = 0;
  686.         }
  687.         else if (inpf->pos_x)
  688.             inpf->pos_x--;
  689.     }
  690.  
  691.     return (result);
  692. }
  693.  
  694. /*
  695.  * inungetc
  696.  *
  697.  * write char back to stream; comparable to ansi's ungetc()
  698.  * different to ugly_inungetc, this will also update the
  699.  * word-position of the input file
  700.  *
  701.  * params: inpf...input file
  702.  *         ch.....char to write back
  703.  * result: ch, if sucessful, else EOF
  704.  */
  705. int inungetc(int ch, INFILE * inpf)
  706. {
  707.     int result = ugly_inungetc(ch, inpf);
  708.  
  709.     if (inpf && (inpf->filepos))
  710.     {
  711.         update_wpos(inpf);
  712.     }
  713.  
  714.     return (result);
  715. }
  716.  
  717. /*
  718.  * inungets
  719.  * write string back to stream
  720.  *
  721.  * params: s......string to write back
  722.  *         inpf...input file
  723.  * result: num of chars written back
  724.  */
  725. size_t inungets(STRPTR s, INFILE * inpf)
  726. {
  727.     size_t ctr = 0;             /* counter, how many chars already written */
  728.     size_t slen = strlen(s);
  729.     STRPTR p = s + (strlen(s) - 1);     /* ptr to current char in string */
  730.     int ch = 0;                 /* current char written, dummy init */
  731.  
  732.     if (slen > 0)
  733.     {
  734.         ctr = 1;                /* unget first char */
  735.         ch = ugly_inungetc(p[0], inpf);
  736.  
  737.         while ((p != s) && (ch != EOF))
  738.         {
  739.             ctr++;              /* inc counter */
  740.             p--;                /* goto next char */
  741.             ch = ugly_inungetc(p[0], inpf);     /* unget current char */
  742.         }
  743.     }
  744.  
  745.     return (ctr);
  746. }
  747.  
  748. /*
  749.  * inungetcw
  750.  * write current word back to stream
  751.  *
  752.  * params: inpf...input file
  753.  * result: num of chars written back
  754.  */
  755. size_t inungetcw(INFILE * inpf)
  756. {
  757.     size_t ctr;                 /* counter how many chars written */
  758.  
  759.     /* unget word */
  760.     ctr = inungets(infgetcw(inpf), inpf);
  761.  
  762.     return (ctr);
  763. }
  764.  
  765. /*
  766.  * inungetcwws
  767.  * write current word & whitespaces back to stream
  768.  *
  769.  * params: inpf...input file
  770.  * result: num of chars written back
  771.  */
  772. size_t inungetcwws(INFILE * inpf)
  773. {
  774.     size_t ctr;                 /* counter how many chars written */
  775.  
  776.     /* unget word & white spaces */
  777.     ctr = inungets(infgetcw(inpf), inpf);
  778.     ctr += inungets(infgetcws(inpf), inpf);
  779.  
  780.     return (ctr);
  781. }
  782.  
  783. /*
  784.  * inf_isws
  785.  *
  786.  * checks if a char is a white space
  787.  *
  788.  * params: ch...char to check for white space
  789.  * result: TRUE if ch was white space
  790.  */
  791. BOOL inf_isws(char ch, INFILE * inpf)
  792. {
  793.     BOOL(*isws) (int ch) = inpf->is_ws;
  794.  
  795.     if (isws == NULL)           /* if no func for is_ws, */
  796.         isws = default_whtspc;  /*   set default function */
  797.  
  798.     return ((*isws) (ch));
  799. }
  800.  
  801. /*
  802.  * infskip_ws
  803.  *
  804.  * skip white spaces; update wspbuf; clear wordbuf
  805.  *
  806.  * TODO: handle wspcbuf-overflow
  807.  */
  808. size_t infskip_ws(INFILE * inpf)
  809. {
  810.     char nxtch;                 /* next char to read */
  811.     size_t ctr = 0;             /* num of ws skipped */
  812.     BOOL ok;
  813.  
  814.     /*
  815.      * set function to determine if a
  816.      * specified char is a white space
  817.      */
  818.     inpf->skipped_ws = FALSE;   /* clear skippe-flag */
  819.  
  820.     /* clear wspcbuf */
  821.     ok = clr_estr(inpf->wspcbuf);
  822.  
  823.     /*
  824.      * loop:  skip white spaces
  825.      */
  826.     nxtch = ugly_infgetc(inpf); /* read next char */
  827.     while ((!infeof(inpf))      /* while not at end of file.. */
  828.            && ok
  829.            && inf_isws(nxtch, inpf))    /* ..and current char is a whtspc */
  830.     {
  831.         ok &= app_estrch(inpf->wspcbuf, nxtch);
  832.         ctr++;
  833.         nxtch = ugly_infgetc(inpf);     /*   read next char */
  834.     }
  835.  
  836.     if (ctr)                    /* any whtspcs skipped? */
  837.         inpf->skipped_ws = TRUE;        /* Y-> set skippe-flag */
  838.  
  839. #if 0
  840.     if (!ok)
  841.     {
  842.         /* TODO: error */ ;
  843.     }
  844. #endif
  845.  
  846.     /*
  847.      * write back last char read
  848.      * (and update word-pos)
  849.      */
  850.     inungetc(nxtch, inpf);
  851.  
  852.     return (ctr);
  853. }
  854.  
  855. /*
  856.  * infgetall
  857.  *
  858.  * returns whole text
  859.  */
  860. STRPTR infgetall(INFILE * inpf)
  861. {
  862.     return (estr2str(inpf->lnbuf));
  863. }
  864.  
  865. /*
  866.  * infgetw
  867.  *
  868.  * read word
  869.  */
  870. STRPTR infgetw(INFILE * inpf)
  871. {
  872.     /* TODO: handle expstr errors */
  873.     int ch = EOF;
  874.     BOOL wordread = FALSE;
  875.     STRPTR thisword = NULL;
  876.     BOOL ok = TRUE;
  877.  
  878.     /* set function for normal chars */
  879.     BOOL(*isnc) (int ch) = inpf->is_nc;
  880.     if (isnc == NULL)
  881.         isnc = default_normch;
  882.  
  883.     /* skip all white spaces */
  884.     infskip_ws(inpf);
  885.  
  886.     ok = clr_estr(inpf->wordbuf);
  887.  
  888.     /*
  889.      * read word until non-normal char is reached
  890.      */
  891.     if (!infeof(inpf))
  892.     {
  893.         ch = infgetc(inpf);
  894.  
  895.         if (((*isnc) (ch)))
  896.         {
  897.             do
  898.             {
  899.                 ok &= app_estrch(inpf->wordbuf, ch);
  900.                 ch = ugly_infgetc(inpf);
  901.                 wordread = TRUE;
  902.                 /* todo: set out-of-mem-flag */
  903.             }
  904.             while ((ch != EOF) && ok && ((*isnc) (ch)));
  905.         }
  906.         else
  907.         {
  908.             ok &= app_estrch(inpf->wordbuf, ch);
  909.         }
  910.  
  911.         if ((ch != EOF) && (wordread))
  912.         {
  913.             inungetc(ch, inpf);
  914.         }
  915.  
  916.         thisword = estr2str(inpf->wordbuf);
  917.     }
  918.     else
  919.     {
  920.         thisword = NULL;
  921.     }
  922.  
  923.     return thisword;
  924. }
  925.  
  926. /*
  927.  * infgotoeol
  928.  *
  929.  * read all chars until CR or EOF
  930.  */
  931. int infgotoeol(INFILE * inpf)
  932. {
  933.     int ch = EOF;
  934.  
  935.     if (!infeof(inpf))
  936.     {
  937.         /*
  938.          * read all chars until CR appears
  939.          */
  940.         do
  941.         {
  942.             ch = ugly_infgetc(inpf);
  943.         }
  944.         while ((ch > 0) && (ch != 0x0a));
  945.  
  946.         /*
  947.          * read LF
  948.          */
  949.         if (ch == 0x0a)
  950.         {
  951.             ch = ugly_infgetc(inpf);
  952.             if (ch != 0x0d)
  953.                 inungetc(ch, inpf);
  954.             ch = 0x0a;
  955.         }
  956.     }
  957.  
  958.     /* return last char read */
  959.     return ch;
  960. }
  961.  
  962. /*
  963.  *-------------------------------------
  964.  * functions for file-positions
  965.  *-------------------------------------
  966.  */
  967.  
  968. /*
  969.  * del_infilepos_nddata
  970.  */
  971. static VOID del_infilepos_nddata(APTR data)
  972. {
  973.     INFILEPOS *pos = (INFILEPOS *) data;
  974.  
  975.     if (pos)
  976.     {
  977.         /* decrese number of pending pos-requests */
  978.         (pos->inpf->pos_count)--;
  979.  
  980.         D(fprintf(stderr, DINF "del pos-req: \"%s\" (%lu,%lu); %lu left\n",
  981.                pos->inpf->filename ? pos->inpf->filename : (STRPTR) "STDIN",
  982.                   pos->x, pos->y, pos->inpf->pos_count));
  983.  
  984.         /* free resources alloceted by pos-request */
  985.         ufree(pos);
  986.     }
  987. }
  988.  
  989. /*
  990.  * cmp_posdata
  991.  */
  992. static int cmp_posdata(APTR data1, APTR data2)
  993. {
  994.     if (data1 == data2)
  995.     {
  996.         return -1;
  997.     }
  998.     else
  999.     {
  1000.         return 0;
  1001.     }
  1002. }
  1003.  
  1004. /*
  1005.  * del_infilepos
  1006.  */
  1007. VOID del_infilepos(INFILEPOS * pos)
  1008. {
  1009.     if (pos)
  1010.     {
  1011.         INFILE *inpf = pos->inpf;
  1012.  
  1013.         /* remove filename */
  1014.         ufreestr(pos->fname);
  1015.  
  1016.         /* check, if file has already been closed by user,
  1017.          * but the last pos-requests has just been deleted
  1018.          * now.
  1019.          * if so, really close the file now
  1020.          */
  1021.         if ((inpf->closed)
  1022.             && (inpf->pos_count == 1)
  1023.             )
  1024.         {
  1025.             D(fprintf(stderr, DINF "  really closing file:\n"));
  1026.             (pos->inpf->pos_count)--;
  1027.             infclose1(inpf);
  1028.         }
  1029.         else
  1030.         {
  1031.             DLNODE *nd = find_dlnode(dll_first(pos->inpf->pos_list),
  1032.                                      pos, cmp_posdata);
  1033.             del_dlnode(pos->inpf->pos_list, nd);
  1034.         }
  1035.     }
  1036. }
  1037.  
  1038. /*
  1039.  * del_all_infilepos
  1040.  */
  1041. VOID del_all_infilepos(INFILE * inpf)
  1042. {
  1043.     del_all_dlnodes(inpf->pos_list);
  1044. }
  1045.  
  1046. /*
  1047.  * new_infilepos
  1048.  */
  1049. static INFILEPOS *new_infilepos_node(INFILE * inpfile, ULONG x, ULONG y)
  1050. {
  1051.     INFILEPOS *pos = umalloc(sizeof(INFILEPOS));
  1052.  
  1053.     if (pos)
  1054.     {
  1055.         DLNODE *nd = app_dlnode(inpfile->pos_list, pos);
  1056.  
  1057.         pos->inpf = inpfile;
  1058.         pos->fname = strclone(inpfile->filename);
  1059.         pos->x = x;
  1060.         pos->y = y;
  1061.         pos->fpos = inpfile->filepos;
  1062.  
  1063.         if (!nd)
  1064.         {
  1065.             del_infilepos_nddata(pos);
  1066.             pos = NULL;
  1067.         }
  1068.         else
  1069.         {
  1070.             (inpfile->pos_count)++;
  1071.         }
  1072.     }
  1073.  
  1074. #if DEBUG_UGLY_INFILE
  1075.     {
  1076.         if (pos)
  1077.         {
  1078.             fprintf(stderr, DINF "new pos-req: \"%s\" (%d,%d); #%d\n",
  1079.                     (char *) inpfile->filename ? (char *) inpfile->filename : (char *) "STDIN",
  1080.                     inpfile->pos_x, inpfile->pos_y, inpfile->pos_count);
  1081.         }
  1082.         else
  1083.         {
  1084.             fprintf(stderr, DINF "new pos-req FAILED\n");
  1085.         }
  1086.     }
  1087. #endif
  1088.  
  1089.     return pos;
  1090. }
  1091.  
  1092. #if 1
  1093. INFILEPOS *new_infilepos(INFILE * inpfile)
  1094. {
  1095.     INFILEPOS *pos =
  1096.     new_infilepos_node(inpfile, infget_x(inpfile), infget_y(inpfile));
  1097.     return pos;
  1098. }
  1099.  
  1100. INFILEPOS *new_winfilepos(INFILE * inpfile)
  1101. {
  1102.     INFILEPOS *pos =
  1103.     new_infilepos_node(inpfile, infget_wx(inpfile), infget_wy(inpfile));
  1104.     return pos;
  1105. }
  1106. #else
  1107. INFILEPOS *new_infilepos(INFILE * inpfile)
  1108. {
  1109.     INFILEPOS *pos =
  1110.     new_infilepos_node(inpfile, inpfile->pos_x, inpfile->pos_y);
  1111.     return pos;
  1112. }
  1113.  
  1114. INFILEPOS *new_winfilepos(INFILE * inpfile)
  1115. {
  1116.     INFILEPOS *pos =
  1117.     new_infilepos_node(inpfile, inpfile->wpos_x, inpfile->wpos_y);
  1118.     return pos;
  1119. }
  1120. #endif
  1121.  
  1122. INFILEPOS *clone_infilepos(INFILEPOS * ipos)
  1123. {
  1124.     INFILEPOS *pos = new_infilepos_node(ipos->inpf, ipos->x, ipos->y);
  1125.     return pos;
  1126. }
  1127.  
  1128. /*
  1129.  * get methodes for pos-req
  1130.  */
  1131. STRPTR ifp_get_fname(INFILEPOS * pos)
  1132. {
  1133.     return (infget_fname(pos->inpf));
  1134. }
  1135.  
  1136. ULONG ifp_get_x(INFILEPOS * pos)
  1137. {
  1138.     return (pos->x);
  1139. }
  1140.  
  1141. ULONG ifp_get_y(INFILEPOS * pos)
  1142. {
  1143.     return (pos->y);
  1144. }
  1145.  
  1146. BOOL set_infile_base(INFILE * inpf, INFILEPOS * pos)
  1147. {
  1148.     D(fprintf(stderr, DINF "set base \"%s\" to \"%s\" (%lu,%lu)\n",
  1149.               inpf->filename ? inpf->filename : (STRPTR) "STDIN",
  1150.               pos->inpf->filename ? pos->inpf->filename : (STRPTR) "STDIN",
  1151.               pos->x, pos->y));
  1152.     reallocstr(&(inpf->filename), pos->fname);
  1153.     inpf->base_x = pos->x;
  1154.     inpf->base_y = pos->y;
  1155.     return TRUE;                /* TODO: handle out of mem */
  1156. }
  1157.  
  1158. BOOL set_infilepos(INFILE * inpf, INFILEPOS * pos)
  1159. {
  1160.     D(fprintf(stderr, DINF "set pos  \"%s\" to \"%s\" (%lu,%lu)\n",
  1161.               inpf->filename ? inpf->filename : (STRPTR) "STDIN",
  1162.               pos->inpf->filename ? pos->inpf->filename : (STRPTR) "STDIN",
  1163.               pos->x, pos->y));
  1164.     reallocstr(&(inpf->filename), pos->fname);
  1165.  
  1166.     inpf->pos_x = pos->x;
  1167.     inpf->pos_y = pos->y;
  1168.     update_wpos(inpf);
  1169.  
  1170.     return TRUE;                /* TODO: handle out of mem */
  1171. }
  1172.